function clone(value: any): any {
    switch (typeof value) {
        case 'object':
            if (Array.isArray(value)) return value.map(v => clone(v));
            const newObj: any = {};
            for (const key in value) newObj[key] = clone(value[key]);
            return newObj;
        default: return value;
    }
    return value;
}

function max(...arr: any[]) {
    return Math.max(...arr.flat());
}

function min(...arr: any[]) {
    return Math.min(...arr.flat());
}

function sum(...arr: any[]) {
    let s = 0;
    arr.flat().forEach(v => s += v);
    return s;
}

function average(...arr: any[]) {
    const s = sum(...arr);
    return s / arr.flat().length;
}

function weightRandom(list: any[]): any[] {
    let totalWeights = 0;
    for (const [, weight] of list)
        totalWeights += weight;

    let random = Math.random() * totalWeights;
    for (const [id, weight] of list)
        if ((random -= weight) < 0)
            return id;
    return list[list.length - 1];
}

function listRandom(list: any[]): any[] {
    return list[Math.floor(Math.random() * list.length)];
}

export { clone, max, min, sum, average, weightRandom, listRandom };